package data;


import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import com.EntityName;
import com.google.appengine.api.datastore.Entity;


public class Reservation extends AbstractData {
	private long id = -1;
	private long displayId;
	private long hotelId;
	private Date date;
	private Date dateCheckin;
	private long span;
	private Date dateTo;
	private Room room;
	private String roomString;
	private RoomType roomType;
	private String roomTypeString;
	private List<PackageByDate> packageByDate;
	private String packageByDateString;
	private long adult;
	private long child;
	private boolean isAssign;
	private Guest guest;
	private String guestString;
	private List<Guest> additionalGuest;
	private String additionalGuestString;
	private ReservationStatus reservationStatus;
	private String reservationStatusString;
	private long order;
	private boolean sellRoom;
	private String note;
	private Group groupId;
	private String groupIdString;
	private long groupIdNumber;
	private List<Task> taskList;
	private String taskListString;
	private CreditCard credit;
	private String creditString;
	private Agency agencyId;
	private String agencyIdString;
	private SourcesBusiness sources;
	private String sourcesString;
	private long extrabed;
	private List<Payment> paymentList;
	private String paymentListString;
	private List<Charge> chargeList;
	private String chargeListString;
	private List<Folio> folioList;
	private String folioListString;	
	private travel travelId;
	private String travelString;
	private List<SubReservation> subReservationList;
	private String subReservationListString;
	private List<AuditTrail> auditTrailsList;
	private String auditTrailsListString;
	private boolean status;
	private boolean avaliable;
	private List<Charge> OtherChargeList;
	private String OtherChargeString;
	private String Objective;
	
	
	public Reservation(){
		
	}
	public Reservation(long id)
	{
		this.id = id;
	
	}
		
	public void setId(long id) {
		this.id = id;
	}

	public long getId() {
		return id;
	}

	public long getDisplayId() {
		return displayId;
	}
	public void setDisplayId(long displayId) {
		this.displayId = displayId;
	}
	public long getHotelId() {
		return hotelId;
	}

	public void setHotelId(long hotelId) {
		this.hotelId = hotelId;
	}

	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
		if(span > 0)
			dateTo = addDays(date,span);
	}
	public Date getDateCheckin() {
		return dateCheckin;
	}

	public void setDateCheckin(Date dateCheckin) {
		this.dateCheckin = dateCheckin;
	}

	public long getSpan() {
		return span;
	}

	public void setSpan(long span) {
		this.span = span;
		if(span > 0)
			dateTo = addDays(date,span);
	}

	public Date getDateTo() {
		return dateTo;
	}

	public Room getRoom() {
		if (room == null && !(roomString == null || roomString.isEmpty())) {
			Room r = new Room(Long.parseLong(roomString));
			r.LoadData();
			room = r;
		}
		return room;
	}

	public void setRoom(Room room) {
		this.roomString = String.format("%d", room.getId());
		this.room = room;
	}
	
	public void setRoomString(String roomString)
	{
		this.roomString = roomString;
	}

	public String getRoomString() {
		return roomString;
	}

	public RoomType getRoomType() {
		if (roomType == null && !(roomTypeString == null || roomTypeString.isEmpty())) {
			RoomType rt = new RoomType(Long.parseLong(roomTypeString));
			rt.LoadData();
			roomType = rt;
		}
		return roomType;
	}

	public void setRoomType(RoomType roomType) {
		this.roomTypeString = String.format("%d", roomType.getId());
		this.roomType = roomType;
	}
	
	public void setRoomTypeString(String roomTypeString)
	{
		this.roomTypeString = roomTypeString;
	}
	
	// for search packageByDate in specific date
	public PackageByDate getPackage(Date date){
		List<PackageByDate> list = getPackageByDate();
		for(PackageByDate p : list)
			if(!date.before(p.getDateFrom()) && date.before(p.getDateTo()))
				return p;
		return null;
	}
	
	public List<PackageByDate> getPackageByDate() {
		if ((packageByDate == null || packageByDate.size() == 0) && 
				!(packageByDateString == null || packageByDateString.isEmpty())) {
			String[] idOfList = SplitList(packageByDateString);
			List<PackageByDate> list = new ArrayList<PackageByDate>();
			for (String id : idOfList) {
				PackageByDate a = new PackageByDate(Long.parseLong(id));
				list.add(a);
			}
			
			for(PackageByDate a : list)
				a.LoadData();
			
			packageByDate = list;
		}
		return packageByDate;
	}

	public void setPackageByDate(List<PackageByDate> packageByDate) {
		this.packageByDateString = CombineList(packageByDate);
		this.packageByDate = packageByDate;
	}

	public String getPackageByDateString() {
		return packageByDateString;
	}

	public void setPackageByDateString(String packageByDateString) {
		this.packageByDateString = packageByDateString;
	}

	public long getAdult() {
		return adult;
	}

	public void setAdult(long adult) {
		this.adult = adult;
	}

	public long getChild() {
		return child;
	}

	public void setChild(long child) {
		this.child = child;
	}

	public boolean isAssign() {
		return isAssign;
	}

	public void setAssign(boolean isAssign) {
		this.isAssign = isAssign;
	}

	public Guest getGuest() {
		if (guest == null && !(guestString == null || guestString.isEmpty())) {
			Guest g = new Guest(Long.parseLong(guestString));
			g.LoadData();
			guest = g;
		}
		return guest;
	}

	public void setGuest(Guest guest) {
		if(guest == null){
			this.guestString =null;
		}
		else{
		this.guestString = String.format("%d", guest.getId());
		}
		this.guest = guest;
	}
	
	public void setGuestString(String guestString)
	{
		this.guestString = guestString;
	}

	public String getGuestString() {
		return guestString;
	}

	public void setAdditionalGuest(List<Guest> additionalGuest) {
		this.additionalGuestString = CombineList(additionalGuest);
		this.additionalGuest = additionalGuest;
	}
	
	public List<Guest> getAdditionalGuest() {
		if ((additionalGuest == null || additionalGuest.size() == 0) && (additionalGuestString != null)) {
			String[] idOfGuest = SplitList(additionalGuestString);
			List<Guest> list = new ArrayList<Guest>();
			for (String idReservation : idOfGuest) {
				Guest c = new Guest(Long.parseLong(idReservation.trim()));
				list.add(c);
			}
			
			for(Guest c : list)
				c.LoadData();
			
			additionalGuest = list;
		}
		return additionalGuest;
	}

	public String getAdditionalGuestString() {
		return additionalGuestString;
	}

	public void setAdditionalGuestString(String additionalGuestString) {
		this.additionalGuestString = additionalGuestString;
	}
	
	public ReservationStatus getReservationStatus() {
		if (reservationStatus == null && !(reservationStatusString == null || reservationStatusString.isEmpty())) {
			ReservationStatus r = new ReservationStatus(Long.parseLong(reservationStatusString));
			r.LoadData();
			reservationStatus = r;
		}
		return reservationStatus;
	}

	public void setReservationStatus(ReservationStatus reservationStatus) {
		this.reservationStatusString = String.format("%d", reservationStatus.getId());
		this.reservationStatus = reservationStatus;
	}
	
	public void setReservationStatusString(String reservationStatusString)
	{
		this.reservationStatusString = reservationStatusString;
	}
	

	public long getOrder() {
		return order;
	}

	public void setOrder(long order) {
		this.order = order;
	}
	
	public boolean getSellRoom() {
		return sellRoom;
	}

	public void setSellRoom(boolean sellRoom) {
		this.sellRoom = sellRoom;
	}

	public String getNote() {
		return note;
	}

	public void setNote(String note) {
		this.note = note;
	}

	public Group getGroupId() {
		if (groupId == null && !(groupIdString == null || groupIdString.isEmpty())) {
			Group r = new Group(Long.parseLong(groupIdString));
			r.LoadData();
			groupId = r;
		}
		return groupId;
	}

	public void setGroupId(Group groupId) {
		this.groupIdString = String.format("%d", groupId.getId());
		this.groupId = groupId;
	}

	public void setGroupIdString(String groupIdString) {
		this.groupIdString = groupIdString;
	}
	
	public double getCost() {
		List<Charge> roomCharge = getChargeList();
		
		double cost = 0;
		for(Charge r : roomCharge)
			cost += r.getChargeAmount();
		
		return cost;
	}
	
	public List<Task> getTaskList() {
		if ((taskList == null || taskList.size() == 0) && !(taskListString == null || taskListString.isEmpty())) {
			String[] idOfList = SplitList(taskListString);
			List<Task> list = new ArrayList<Task>();
			for (String id : idOfList) {
				Task a = new Task(Long.parseLong(id));
				list.add(a);
			}
			
			for(Task a : list)
				a.LoadData();
			
			taskList = list;
		}
		return taskList;
	}
	
	public void setTaskList(List<Task> taskList) {
		this.taskListString = CombineList(taskList);
		this.taskList = taskList;
	}
	
	public List<Payment> getPaymentList() {
		if ((paymentList == null || paymentList.size() == 0) && !(paymentListString == null || paymentListString.isEmpty())) {
			String[] idOfList = SplitList(paymentListString);
			List<Payment> list = new ArrayList<Payment>();
			if(idOfList.length == 1 && idOfList[0].equals("")){
				paymentList = null;
			}else{
				for (String id : idOfList) {
					Payment a = new Payment(Long.parseLong(id));
					list.add(a);
				}
				
				for(Payment a : list)
					a.LoadData();
				
				paymentList = list;			
			}

		}
		return paymentList;
	}

	public void setPaymentList(List<Payment> paymentList) {
		this.paymentListString = CombineList(paymentList);
		this.paymentList = paymentList;
	}

	public String getPaymentListString() {
		return paymentListString;
	}

	public void setPaymentListString(String paymentListString) {
		this.paymentListString = paymentListString;
	}

	public List<Charge> getChargeList() {
		if ((chargeList == null || chargeList.size() == 0) && (chargeListString != null)) {
			String[] idOfList = SplitList(chargeListString);
			List<Charge> list = new ArrayList<Charge>();
			for (String id : idOfList) {
				Charge a = new Charge(Long.parseLong(id));
				list.add(a);
			}
			
			for(Charge a : list)
				a.LoadData();
			
			chargeList = list;
		}
		return chargeList;
	}
	
	public List<Charge> reloadChargeList() {
		if ((chargeListString != null)) {
			String[] idOfList = SplitList(chargeListString);
			List<Charge> list = new ArrayList<Charge>();
			for (String id : idOfList) {
				Charge a = new Charge(Long.parseLong(id));
				list.add(a);
			}
			
			for(Charge a : list)
				a.LoadData();
			
			chargeList = list;
		}
		return chargeList;
	}

	public void setChargeList(List<Charge> chargeList) {
		this.chargeListString = CombineList(chargeList);
		this.chargeList = chargeList;
	}

	public String getChargeListString() {
		return chargeListString;
	}

	public void setChargeListString(String chargeListString) {
		this.chargeListString = chargeListString;
	}

	public List<Folio> getFolioList() {
		if ((folioList == null || folioList.size() == 0) && !(folioListString == null || folioListString.isEmpty())) {
			String[] idOfList = SplitList(folioListString);
			List<Folio> list = new ArrayList<Folio>();
			for (String id : idOfList) {
				Folio a = new Folio(Long.parseLong(id));
				list.add(a);
			}
			list.removeAll(Collections.singleton(null)); 
			for(Folio a : list)
				
				a.LoadData();
				folioList = list;
		}
		return folioList;
	}

	public void setFolioList(List<Folio> folioList) {
		this.folioListString = CombineList(folioList);
		this.folioList = folioList;
	}

	public String getFolioListString() {
		return folioListString;
	}

	public void setFolioListString(String folioListString) {
		this.folioListString = folioListString;
	}
	
	public long getGroupIdNumber() {
		return groupIdNumber;
	}

	public void setGroupIdNumber(long groupIdNumber) {
		this.groupIdNumber = groupIdNumber;
	}


	public String getTaskListString() {
		return taskListString;
	}

	public void setTaskListString(String taskListString) {
		this.taskListString = taskListString;
	}
	
	public CreditCard getCredit() {
		if (credit == null && !(creditString == null || creditString.isEmpty())) {
			if(creditString == "0"){
				credit = null;
			}else{
				CreditCard r = new CreditCard(Long.parseLong(creditString));
				r.LoadData();
				credit = r;
			}
			
		}
		return credit;
	}

	public void setCredit(CreditCard credit) {
		this.creditString = String.format("%d", credit.getId());
		this.credit = credit;
	}

	public void setCreditString(String creditString) {
		this.creditString = creditString;
	}
	
	public String getCreditString() {
		return creditString;
	}

	public String getGroupIdString() {
		return groupIdString;
	}
	
	public Agency getAgencyId() {
		if (agencyId == null && !(agencyIdString == null || agencyIdString.isEmpty())) {
			if(agencyIdString == "0"){
				agencyId = null;
			}else{
				Agency r = new Agency(Long.parseLong(agencyIdString));
				r.LoadData();
				agencyId = r;
			}
			
		}
		return agencyId;
	}
	
	public travel getTravelId() {
		if (travelId == null && !(travelString == null || travelString.isEmpty())) {
			if(travelString.equals("0")){
				travelId = null;
			}else{
				travel r = new travel(Long.parseLong(travelString));
				r.LoadData();
				travelId = r;
			}
		}
		return travelId;
	}

	public void setTravelId(travel travelId) {
		this.travelString = String.format("%d", travelId.getId());
		this.travelId = travelId;
	}

	public String getTravelString() {
		return travelString;
	}

	public void setTravelString(String travelString) {
		this.travelString = travelString;
	}

	public String getAgencyIdString() {
		return agencyIdString;
	}

	public void setAgencyIdString(String agencyIdString) {
		this.agencyIdString = agencyIdString;
	}

	public SourcesBusiness getSources() {
		if (sources == null && !(sourcesString == null || sourcesString.isEmpty())) {
			SourcesBusiness c = new SourcesBusiness(Long.parseLong(sourcesString));	
			c.LoadData();
			sources = c;
		}
		return sources;
	}

	public void setSources(SourcesBusiness sources) {
		this.sourcesString = String.format("%d", sources.getId());
		this.sources = sources;
	}

	public void setSourcesString(String sourcesString) {
		this.sourcesString = sourcesString;
	}
	public long getExtrabed() {
		return extrabed;
	}

	public void setExtrabed(long extrabed) {
		this.extrabed = extrabed;
	}

	public List<SubReservation> getSubReservationList() {
		//workaround by Newss
		if(subReservationListString == null)
			return new ArrayList<SubReservation>();
		if ((subReservationList == null || subReservationList.size() == 0) && !(subReservationListString == null || subReservationListString.isEmpty())) {
			String[] ids = SplitList(subReservationListString);
			List<SubReservation> list = new ArrayList<SubReservation>();
			for (String id : ids) {
				SubReservation a = new SubReservation(Long.parseLong(id));
				list.add(a);
			} 
			for(SubReservation a : list)
				a.LoadData();
			subReservationList = list;
		}
		return subReservationList;
	}

	public void setSubReservationList(List<SubReservation> subReservationList) {
		this.subReservationListString = CombineList(subReservationList);
		this.subReservationList = subReservationList;
	}
	
	public List<AuditTrail> getAuditTrailsList() {
		//workaround by Newss
		if(auditTrailsListString == null)
			return new ArrayList<AuditTrail>();
		if ((auditTrailsList == null || auditTrailsList.size() == 0) && !(auditTrailsListString == null || auditTrailsListString.isEmpty())) {
			String[] ids = SplitList(auditTrailsListString);
			List<AuditTrail> list = new ArrayList<AuditTrail>();
			for (String id : ids) {
				AuditTrail a = new AuditTrail(Long.parseLong(id));
				list.add(a);
			} 
			for(AuditTrail a : list)
				a.LoadData();
			auditTrailsList = list;
		}
		return auditTrailsList;
	}

	public void addAuditTrails(AuditTrail auditTrail) {
		String tmp = CombineList(auditTrailsList);
		if(!tmp.isEmpty())
			tmp += ",";
		this.auditTrailsListString = tmp + auditTrail.getId();
		if(this.auditTrailsList == null)
			this.auditTrailsList = new ArrayList<AuditTrail>();
		this.auditTrailsList.add(auditTrail);
	}
	
	public boolean isStatus() {
		return status;
	}

	public void setStatus(boolean status) {
		this.status = status;
	}

	public boolean isAvaliable() {
		return avaliable;
	}

	public void setAvaliable(boolean avaliable) {
		this.avaliable = avaliable;
	}

	public String getRoomTypeString() {
		return roomTypeString;
	}

	public String getReservationStatusString() {
		return reservationStatusString;
	}

	public String getSourcesString() {
		return sourcesString;
	}

	public String getSubReservationListString() {
		return subReservationListString;
	}

	public void setSubReservationListString(String subReservationListString) {
		this.subReservationListString = subReservationListString;
	}
	public List<Charge> getOtherChargeList() {
		if ((OtherChargeList == null || OtherChargeList.size() == 0) && (OtherChargeString != null)) {
			String[] idOfList = SplitList(OtherChargeString);
			List<Charge> list = new ArrayList<Charge>();
			for (String id : idOfList) {
				Charge a = new Charge(Long.parseLong(id));
				list.add(a);
			}
			for(Charge a : list)
				a.LoadData();
			OtherChargeList = list;
		}
		return OtherChargeList;
	}

	public void setOtherChargeList(
			List<Charge> OtherChargeList) {
		this.OtherChargeString =CombineList(OtherChargeList);
		this.OtherChargeList = OtherChargeList;
	}

	public String getOtherChargeString() {
		return OtherChargeString;
	}

	public void setOtherChargeString(String OtherChargeString) {
		this.OtherChargeString = OtherChargeString;
	}
	
	public String getObjective() {
		return Objective;
	}
	public void setObjective(String Objective) {
		this.Objective = Objective;
	}
	@Override
	public Entity getEntity()
	{
		Entity item;
		if(this.key == null)
			item = new Entity(EntityName.Reservation);
		else
			item = new Entity(this.key);
		item.setProperty("displayId", this.displayId);
		item.setProperty("hotelId", this.hotelId);
		item.setProperty("date", this.date);
		item.setProperty("dateCheckin", this.dateCheckin);
		item.setProperty("span", this.span);
		item.setProperty("dateTo", this.dateTo);
		item.setProperty("roomId", this.roomString);
		item.setProperty("roomType", this.roomTypeString);
		item.setProperty("packageByDate", this.packageByDateString);
		item.setProperty("adult", this.adult);
		item.setProperty("child", this.child);
		item.setProperty("isAssign", this.isAssign);
		item.setProperty("GuestId", this.guestString);
		item.setProperty("AdditionalGuestList", this.additionalGuestString);
		item.setProperty("ReservationStatus", this.reservationStatusString);
		item.setProperty("order",this.order);
		item.setProperty("sellRoom",this.sellRoom);
		item.setProperty("note",this.note);
		item.setProperty("groupId",this.groupIdString);
		item.setProperty("groupIdNumber",this.groupIdNumber);
		item.setProperty("taskList", this.taskListString);
		item.setProperty("creditCard", this.creditString);
		item.setProperty("agencyId", this.agencyIdString);
		item.setProperty("sources",this.sourcesString);
		item.setProperty("extrabed",this.extrabed);
		item.setProperty("travelId", this.travelString);
		item.setProperty("status", this.status);
		item.setProperty("avaliable", this.avaliable);
		item.setProperty("paymentList",this.paymentListString);
		item.setProperty("chargeList",this.chargeListString);
		item.setProperty("folioList",this.folioListString);
		item.setProperty("subReservationList",this.subReservationListString);
		item.setProperty("auditTrailsList", this.auditTrailsListString);
		item.setProperty("OtherCharge",this.OtherChargeString);
		item.setProperty("Objective",this.Objective);
		return item;
	}

	@Override
	public void setEntity(Entity entity) {
		
		this.id = entity.getKey().getId();
		this.displayId = (Long) entity.getProperty("displayId");
		this.hotelId = (Long) entity.getProperty("hotelId");
		this.date = (Date) entity.getProperty("date");
		this.dateCheckin = (Date) entity.getProperty("dateCheckin");
		this.span= (Long) entity.getProperty("span");
		this.dateTo= (Date) entity.getProperty("dateTo");
		this.roomString= (String) entity.getProperty("roomId");
		this.roomTypeString= (String) entity.getProperty("roomType");
		
		if(entity.getProperty("packageByDate")==null||entity.getProperty("packageByDate") ==""){
			this.packageByDateString = "";
		}else{
			this.packageByDateString= (String) entity.getProperty("packageByDate");
		}
		
		this.adult= (Long) entity.getProperty("adult");
		this.child= (Long) entity.getProperty("child");
		this.isAssign= (Boolean) entity.getProperty("isAssign");
		this.guestString= (String) entity.getProperty("GuestId");
		this.additionalGuestString= (String) entity.getProperty("AdditionalGuestList");
		this.reservationStatusString= (String) entity.getProperty("ReservationStatus");
		this.order =(Long) entity.getProperty("order");
		//TODO: must be remove 
		if(entity.getProperty("sellRoom")==null||entity.getProperty("sellRoom") ==""){
			this.sellRoom =false;
		}else{
			this.sellRoom =(Boolean)entity.getProperty("sellRoom");
		}

		this.note =(String) entity.getProperty("note");
		this.groupIdString =(String) entity.getProperty("groupId");
		//TODO: must be remove
		if(entity.getProperty("groupIdNumber")==null||entity.getProperty("groupIdNumber") ==""){
			this.groupIdNumber = 0;
		}else{
			this.groupIdNumber = (Long)entity.getProperty("groupIdNumber");
		}
		this.taskListString = (String) entity.getProperty("taskList");
		this.creditString = (String) entity.getProperty("creditCard");
		this.agencyIdString = (String) entity.getProperty("agencyId");
		this.sourcesString =(String) entity.getProperty("sources");
		this.travelString= (String) entity.getProperty("travelId");
		this.status = (Boolean) entity.getProperty("status");
		this.avaliable = (Boolean) entity.getProperty("avaliable");
		this.key = entity.getKey();
		//TODO: must be remove
		if(entity.getProperty("extrabed")==null||entity.getProperty("extrabed") ==""){
			this.extrabed = 0;
		}else{
			this.extrabed = (Long) entity.getProperty("extrabed");
		}
		this.paymentListString = (String) entity.getProperty("paymentList");
		this.chargeListString = (String) entity.getProperty("chargeList");
		this.folioListString = (String) entity.getProperty("folioList");
		this.subReservationListString = (String) entity.getProperty("subReservationList");
		this.auditTrailsListString = (String) entity.getProperty("auditTrailsList");
		this.OtherChargeString=(String) entity.getProperty("OtherCharge");
		this.Objective =(String) entity.getProperty("Objective");
		this.key = entity.getKey();
	}
	
	public void LoadData() {
		if (this.id > -1) {
			Entity entity = LoadData(EntityName.Reservation, this.id);
			setEntity(entity);
		}
	}
}

